﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;

namespace Central.Linq {

	/// <summary>
	/// Определение сортировки для запроса
	/// </summary>
	public class SortManager {
		#region конструктор

		/// <summary>
		/// Создает экземпляр коллекции сортировщиков
		/// </summary>
		public SortManager() {
			sortDefinitions = new Collection<SortDefinition>();
		}

		#endregion конструктор

		#region [+] cвойства

		private Collection<SortDefinition> sortDefinitions;

		/// <summary>
		/// Коллекция сортировки
		/// </summary>
		public IEnumerable<SortDefinition> SortDefinitions { get { return sortDefinitions; } }

		/// <summary>
		/// возвращаемый предикат сортировки
		/// </summary>
		public string Predicate {
			get {
				return this.GeneratePredicate();
			}
		}

		/// <summary>
		/// Возвращаемое количество полей сортировки
		/// </summary>
		public int Count {
			get {
				return this.sortDefinitions == null ? 0 : this.sortDefinitions.Count;
			}
		}

		#endregion [+] cвойства

		#region методы

		/// <summary>
		/// Сравнение объектов
		/// </summary>
		/// <param name="obj"></param>
		/// <returns></returns>
		public override bool Equals(object obj) {
			return Equals(obj as SortManager);
		}

		/// <summary>
		/// Сравнение объектов SortManager
		/// </summary>
		/// <param name="other"></param>
		/// <returns></returns>
		public bool Equals(SortManager other) {
			if (other == null || ((other.SortDefinitions == null) != (this.SortDefinitions == null)))
				return false;

			if (other.SortDefinitions == null && this.SortDefinitions == null)
				return true;

			if (other.SortDefinitions.SequenceEqual(this.SortDefinitions))
				return true;

			return true;
		}

		/// <summary>
		/// Получение Hash кода объекта SortManager
		/// </summary>
		/// <returns></returns>
		public override int GetHashCode() {
			return this.GetHashCode();
		}

		/// <summary>
		/// Метод добавления SortDefinition в коллекцию
		/// </summary>
		/// <param name="sortDefinition"></param>
		public void Add(SortDefinition sortDefinition) {
			if (sortDefinition == null)
				return;

			if (this.sortDefinitions == null)
				this.sortDefinitions = new Collection<SortDefinition>();

			if (this.sortDefinitions.Contains(sortDefinition))
				this.sortDefinitions.Remove(sortDefinition);

			this.sortDefinitions.Add(sortDefinition);
		}

		/// <summary>
		/// Метод вставки SortDefinition в коллекцию
		/// </summary>
		/// <param name="index">место вставки</param>
		/// <param name="sortDefinition">определение сортировки</param>
		public void Insert(int index, SortDefinition sortDefinition) {
			if (sortDefinition == null)
				return;

			if (this.sortDefinitions == null)
				this.sortDefinitions = new Collection<SortDefinition>();

			if (this.sortDefinitions.Contains(sortDefinition))
				this.sortDefinitions.Remove(sortDefinition);

			this.sortDefinitions.Insert(index, sortDefinition);
		}

		/// <summary>
		/// Метод удаления SortDefinition из коллекции
		/// </summary>
		/// <param name="sortDefinition"></param>
		public void Remove(SortDefinition sortDefinition) {
			if (sortDefinition == null)
				return;

			if (this.sortDefinitions != null)
				this.sortDefinitions.Remove(sortDefinition);
		}

		/// <summary>
		/// Метод очищения коллекции
		/// </summary>
		public void Clear() {
			if (this.sortDefinitions != null)
				this.sortDefinitions.Clear();
		}

		#endregion методы

		#region скрытые методы

		private string GeneratePredicate() {
			StringBuilder ret = new StringBuilder();
			if (this.Count > 0) {
				lock (this.sortDefinitions) {
					bool isMoreThanOne = false;
					foreach (SortDefinition item in this.SortDefinitions) {
						if (!isMoreThanOne) {
							ret.Append(string.Concat(item.Name, " ", item.Value));
							isMoreThanOne = true;
						}
						else {
							ret.Append(string.Concat(", ", item.Name, " ", item.Value));
						}
					}
				}
			}
			return ret.ToString();
		}

		#endregion скрытые методы
	}
}